#include "EnDictionary.h"

#include <fstream>
#include <iostream>
#include <set>
#include <sstream>

#include "configure.h"
#include "mylogger.h"

using std::ifstream;
using std::istringstream;
using std::ofstream;
using std::set;

EnDictionary::EnDictionary() {
    getDict();
    getIndexTable();
}

vector<pair<string, int>> EnDictionary::doQuery(const string& word) {
    string lowerWord = toLower(word);
    set<pair<string, int>> cutRepeat;

    for (const char& ch : lowerWord) {
        string chToString(1, ch);
        const set<int>& lineNums = _indexTable[chToString];
        for (auto& line : lineNums) {
            cutRepeat.insert(_dict[line - 1]);
        }
    }
    return vector<pair<string, int>>(cutRepeat.begin(), cutRepeat.end());
}

void EnDictionary::getDict() {
    string EnDictPath =
        Configuration::getInstance()->getConfigMap()["EN_DICT_OUTPUT_PATH"];
    ifstream enstream(EnDictPath);
    if (!enstream.good()) {
        LogError("Open English frequency file failed");
        abort();
    }
    string line, key;
    int value;
    while (getline(enstream, line)) {
        istringstream iss(line);
        if (iss >> key >> value) {
            _dict.emplace_back(key, value);
        } else {
            std::cout << "iss failed" << std::endl;
        }
    }
    enstream.close();
}

void EnDictionary::getIndexTable() {
    string EnIndexPath =
        Configuration::getInstance()->getConfigMap()["EN_INDEX_OUTPUT_PATH"];
    ifstream enIndexStream(EnIndexPath);
    if (!enIndexStream.good()) {
        LogError("Open English index file failed");
        abort();
    }
    string line;
    while (getline(enIndexStream, line)) {
        istringstream iss(line);
        string key;
        iss >> key;
        int index;
        while (iss >> index) {
            _indexTable[key].insert(index);
        }
    }
    enIndexStream.close();
}

string EnDictionary::toLower(const string& str) {
    string tmp = str;
    for (auto& ch : tmp) {
        if (std::isupper(ch)) {
            ch = std::tolower(ch);
        }
    }
    return tmp;
}
